﻿using System;
using System.Collections.Generic;
using System.Linq;
using Android;
using Android.App;
using Android.Content;
using Android.Graphics;
using Android.Net.Wifi.Aware;
using Android.OS;
using Android.Renderscripts;
using AndroidX.AppCompat.App;
using Android.Util;
using Android.Views;
using Android.Widget;
using FantasticMusicPlayer;
using FantasticMusicPlayer.dbo.Model;
using NightPlayer.windows.utils;
using AndroidX.Fragment.App;
using AndroidX.ViewPager.Widget;
using Android.Content.Res;
using Android.Content.PM;
using NightPlayer.views;


namespace NightPlayer
{
    [Activity(
        Label = "@string/app_name",
        Exported =true, 
        Theme = "@style/AppTheme",
        LaunchMode = Android.Content.PM.LaunchMode.SingleInstance,
        ScreenOrientation = Android.Content.PM.ScreenOrientation.Unspecified,
        ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.ScreenLayout | ConfigChanges.UiMode | ConfigChanges.ColorMode
        )
        ]
    public class MainActivity : BaseActivity
    {
        #region View Model
        private ListView listMain { get => FindViewById<ListView>(Resource.Id.listMain); }
        private ListView listFolder { get => FindViewById<ListView>(Resource.Id.listFolder); }
        private TextView lblTotalTime { get => FindViewById<TextView>(Resource.Id.lblTotalTime); }
        private ImageButton btnNext { get => FindViewById<ImageButton>(Resource.Id.btnNext); }
        private ImageButton btnPlay { get => FindViewById<ImageButton>(Resource.Id.btnPlay); }
        private ImageButton btnPrev { get => FindViewById<ImageButton>(Resource.Id.btnPrev); }
        private TextView lblCurrentTime { get => FindViewById<TextView>(Resource.Id.lblCurrentTime); }
        private ImageButton btnPlaylist { get => FindViewById<ImageButton>(Resource.Id.btnPlayList); }
        private ImageButton btnFav { get => FindViewById<ImageButton>(Resource.Id.btnFav); }
        private SeekBar numProgress { get => FindViewById<SeekBar>(Resource.Id.numProgress); }
        private SeekBar numBbtVol { get => FindViewById<SeekBar>(Resource.Id.numBbtVol); }
        private SeekBar numNoiseVol { get => FindViewById<SeekBar>(Resource.Id.numNoiseVol); }
        private SeekBar numMainVol { get => FindViewById<SeekBar>(Resource.Id.numMainVol); }
        private SeekBar numDynamicRangeCompressing { get => FindViewById<SeekBar>(Resource.Id.numDynamicRangeCompressing); }
        private ImageButton btnSleepTimer { get => FindViewById<ImageButton>(Resource.Id.btnSleepTimer); }
        private TextView lblSleepTimer { get => FindViewById<TextView>(Resource.Id.lblSleepTimer); }
        private TextView lblSleepTimer2 { get => FindViewById<TextView>(Resource.Id.lblSleepTimer2); }
        private TextView lblLoopMode { get => FindViewById<TextView>(Resource.Id.lblLoopMode); }
        private TextView lblShuffeMode { get => FindViewById<TextView>(Resource.Id.lblShuffeMode); }
        private ImageButton btnBbtMode { get => FindViewById<ImageButton>(Resource.Id.btnBbtMode); }
        private ImageButton btnNoiseMode { get => FindViewById<ImageButton>(Resource.Id.btnNoiseMode); }
        private ImageButton btnBassBoost { get => FindViewById<ImageButton>(Resource.Id.btnBassBoost); }
        private ImageButton btnSrsWow { get => FindViewById<ImageButton>(Resource.Id.btnSrsWow); }
        private ImageButton btnShuffeMode { get => FindViewById<ImageButton>(Resource.Id.btnShuffeMode); }
        private ImageButton btnLoopMode { get => FindViewById<ImageButton>(Resource.Id.btnLoopMode); }
        private ImageButton btnVolume { get => FindViewById<ImageButton>(Resource.Id.btnVolume); }
        private ImageButton btnVolumeClose { get => FindViewById<ImageButton>(Resource.Id.btnVolumeClose); }
        private ImageButton btnSettings { get => FindViewById<ImageButton>(Resource.Id.btnSettings); }
        private ImageView imgCover { get => FindViewById<ImageView>(Resource.Id.imgCover); }
        private ImageView imgBg { get => FindViewById<ImageView>(Resource.Id.imgBg); }
        private FrameLayout bgContainer { get => FindViewById<FrameLayout>(Resource.Id.bgContainer); }
        private ImageButton BtnExit { get => FindViewById<ImageButton>(Resource.Id.BtnExit); }
        private TextView lblSubtitle { get => FindViewById<TextView>(Resource.Id.lblSubtitle); }
        private TextView lblTitle { get => FindViewById<TextView>(Resource.Id.lblTitle); }
        private LinearLayout tblVolume { get => FindViewById<LinearLayout>(Resource.Id.tblVolume); }
        #endregion

        public class ViewFragment : AndroidX.Fragment.App.Fragment
        {
            public View view = null;
            public ViewFragment(LayoutInflater inflater,int layoutId)
            {
                view = inflater.Inflate(layoutId, null, false);
            }
            public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
            {
                var x = view.Parent;
                if(x != null && x is ViewGroup)
                {
                    ((ViewGroup)x).RemoveView(view);
                }
                return view;
            }

            public override void OnSaveInstanceState(Bundle outState)
            {
                // base.OnSaveInstanceState(outState);
            }
        }

        public class ViewPageAdapter : FragmentPagerAdapter
        {
            public List<ViewFragment> fragments;

            public ViewPageAdapter(AndroidX.Fragment.App.FragmentManager manager,List<ViewFragment> fragments):base(manager)
            {
                this.fragments = fragments;
            }

            public override int Count => fragments.Count;

            public override AndroidX.Fragment.App.Fragment GetItem(int position)
            {
                return fragments[position];
            }
        }

        public override View FindViewById(int id)
        {
            var result = base.FindViewById(id);
            if(result != null) { return result; }
            if(subPages != null)
            {
                foreach (ViewFragment item in subPages.fragments)
                {
                    result = item.view.FindViewById(id);
                    if(result != null)
                    {
                        return result;
                    }
                }
            }
            return null;
        }

        private void SetActive(int pageButtonId,bool active)
        {
            var button = FindViewById<Button>(pageButtonId);
            button.TextSize = 18f; 
            button.SetTextColor(ColorStateList.ValueOf(new Color(active ? GetColor(Resource.Color.selected_item) : GetColor(Resource.Color.default_item))));
            button.Typeface = active ? Typeface.DefaultBold : Typeface.Default;
        }
        private void Pager_PageSelected(object sender, ViewPager.PageSelectedEventArgs e)
        {
            SetActive(Resource.Id.btnPage0, e.Position == 0);
            SetActive(Resource.Id.btnPage1, e.Position == 1);
            SetActive(Resource.Id.btnPage2, e.Position == 2);
            SetActive(Resource.Id.btnPage3, e.Position == 3);
            if(e.Position == 3)
            {
                UpdateUIState();
            }
            else
            {
                tblVolume.Visibility = ViewStates.Gone;
            }
            if(isLandspace && e.Position == 0)
            {
                pager.CurrentItem = 1;
            }
        }

        ViewPageAdapter subPages = null;
        ViewPager pager = null;


        void InitUI()
        {
            pager = FindViewById<ViewPager>(Resource.Id.viewPager);
            List<ViewFragment> pages = new List<ViewFragment>();
            pages.Add(new ViewFragment(this.LayoutInflater, Resource.Layout.page_folder));
            pages.Add(new ViewFragment(this.LayoutInflater, Resource.Layout.page_playlist));
            pages.Add(new ViewFragment(this.LayoutInflater, isSmallScreen ? Resource.Layout.page_play_small : Resource.Layout.page_play));
            pages.Add(new ViewFragment(this.LayoutInflater, Resource.Layout.page_extra));
            subPages = new ViewPageAdapter(SupportFragmentManager, pages);
            pager.Adapter = subPages;
            pager.SetCurrentItem(2, false);
            pager.PageSelected += Pager_PageSelected;
            FindViewById<Button>(Resource.Id.btnPage0).Click += (sender,e) => { pager.CurrentItem = 0; };
            FindViewById<Button>(Resource.Id.btnPage1).Click += (sender, e) => { pager.CurrentItem = 1; };
            FindViewById<Button>(Resource.Id.btnPage2).Click += (sender,e) => { pager.CurrentItem = 2; };
            FindViewById<Button>(Resource.Id.btnPage3).Click += (sender,e) => { pager.CurrentItem = 3; };
            pager.PageScrolled += Pager_PageScrolled;
            btnSettings.Click += BtnSettings_Click;
        }

        private void BtnSettings_Click(object? sender, EventArgs e)
        {
            StartActivity(new Intent(this, typeof(SettingActivity)));
        }

        private void Pager_PageScrolled(object sender, ViewPager.PageScrolledEventArgs e)
        {
            btnSettings.Visibility = e.Position == 2 ? ViewStates.Visible : ViewStates.Gone;
            if (isSmallScreen || imgBg == null)
            {
                return;
            }
            float totalPosition = e.Position + e.PositionOffset;
            if(e.Position >= 1 && e.Position <= 3)
            {
                float centerPos = 2.0f;
                float deltaPos = totalPosition - centerPos;
                { // 唱片视差
                    float dx = dip2px(80) * deltaPos;
                    imgCover.TranslationX = dx;
                }
                { // 背景过渡
                    float dx = - bgContainer.Width / 2 * deltaPos;
                    imgBg.TranslationX = dx;
                    float da = 1 - Math.Abs(deltaPos);
                    if(da > 1) { da = 1; }
                    if(da < 0) { da = 0; }
                    imgBg.Alpha = da;
                }
            }

            if (isLandspace)
            {
                // block page 0
                if(e.Position < 1)
                {
                    subPages.fragments[1].view.ScaleX = 1.0f + (1 - e.PositionOffset) * 0.05f;
                    subPages.fragments[1].view.TranslationX = - (1f - e.PositionOffset) * pager.Width + (pager.Width * 0.025f * (1f - e.PositionOffset));
                }
                else
                {
                    subPages.fragments[1].view.TranslationX = 0;
                    subPages.fragments[1].view.ScaleX = 1.0f;
                }
            }
        }
        private bool isSmallScreen = false;
        private bool isLandspace = false;
        private void detectScreenSize()
        {
            DisplayMetrics metrics = new DisplayMetrics();
            WindowManager.DefaultDisplay.GetMetrics(metrics);
            isLandspace = Resources.Configuration.Orientation == Android.Content.Res.Orientation.Landscape;
            float height = isLandspace ? metrics.WidthPixels : metrics.HeightPixels;
            float density = Resources.DisplayMetrics.Density;
            float heightDp = height / density;
            isSmallScreen = heightDp < 540;
        }

        protected override void OnSaveInstanceState(Bundle outState)
        {
            // nothing is required to be saved
            // base.OnSaveInstanceState(outState);
        }

        public override void OnSaveInstanceState(Bundle outState, PersistableBundle outPersistentState)
        {
            // base.OnSaveInstanceState(outState, outPersistentState);
        }

        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            detectScreenSize();
            if (isEink)
            {
                RequestedOrientation = ScreenOrientation.Portrait;
            }
            SetContentView(isSmallScreen ? Resource.Layout.activity_main_small : Resource.Layout.activity_main);
            
            
            InitUI();
            if (isSmallScreen)
            {
                Window.DecorView.SystemUiVisibility = (StatusBarVisibility)5894;
            }
            else {

                Window?.SetNavigationBarColor(Android.Graphics.Color.Black);
            }
            BassPlayerImpl player = PlayerService.player;
            if (player == null) { Finish(); return; }
            IntentFilter inf = new IntentFilter();
            inf.AddAction(PlayerService.BROADCAST_COVERCHANGED);
            inf.AddAction(PlayerService.BROADCAST_SONGCHANGED);
            inf.AddAction(PlayerService.BROADCAST_PLAYCHANGE);
            inf.AddAction(PlayerService.BROADCAST_EXIT);
            inf.AddAction(PlayerService.BROADCAST_FAV_ON);
            inf.AddAction(PlayerService.BROADCAST_FAV_OFF);
            eventReceiver = new EventListener(this);
            if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
            {

                RegisterReceiver(eventReceiver, inf, ReceiverFlags.Exported);
            }
            else
            {

                RegisterReceiver(eventReceiver, inf);
            }

            btnNext.Click += BtnNext_Click;
            btnPrev.Click += BtnPrev_Click;
            btnPlay.Click += BtnPlay_Click;
            BtnExit.Click += BtnExit_Click;
            btnFav.Click += BtnFav_Click;
            numProgress.StartTrackingTouch += delegate { seekbarTracking = true; };
            numProgress.StopTrackingTouch += NumProgress_StopTrackingTouch;
            numProgress.ProgressChanged += NumProgress_ProgressChanged;
            numBbtVol.ProgressChanged += NumVol_ProgressChanged;
            numNoiseVol.ProgressChanged += NumVol_ProgressChanged;
            numMainVol.ProgressChanged += NumVol_ProgressChanged;
            numBbtVol.StopTrackingTouch += NumBbtVol_StopTrackingTouch;
            numMainVol.StopTrackingTouch += NumBbtVol_StopTrackingTouch;
            numNoiseVol.StopTrackingTouch += NumBbtVol_StopTrackingTouch;
            numDynamicRangeCompressing.StopTrackingTouch += NumDynamicRangeCompressing_StopTrackingTouch;
            btnSleepTimer.Click += BtnSleepTimer_Click;
            btnSleepTimer.LongClick += BtnSleepTimer_LongClick;
            btnLoopMode.Click += BtnLoopMode_Click;
            btnShuffeMode.Click += BtnShuffeMode_Click;
            btnBassBoost.Click += BtnBassBoost_Click;
            btnSrsWow.Click += BtnSrsWow_Click;
            btnSrsWow.SetImageResource(dspImages[PrefSrsWow]);
            btnNoiseMode.Click += BtnNoiseMode_Click; 
            btnNoiseMode.LongClick += BtnNoiseMode_LongClick;
            btnBbtMode.Click += BtnBbtMode_Click;
            btnBbtMode.LongClick += BtnBbtMode_LongClick;
            btnVolume.Click += BtnVolume_Click;
            btnVolumeClose.Click += BtnVolume_Click;
            lblTitle.RequestFocus();
            lblSubtitle.RequestFocus();
            lblTitle.RequestFocusFromTouch();
            lblSubtitle.RequestFocusFromTouch();
            ticking = new Action(OnTick);
            btnPlaylist.Click += BtnPlaylist_Click;
            listFolder.Adapter = (new FolderAdapter(PlayerService.playerController.AllPlayList, this, ListFolder_ItemClick));
            listMain.Adapter = (new SongAdapter(PlayerService.playerController.CurrentList, this, ListMain_ItemClick));
            hWnd.PostDelayed(ticking, 1000);
            btnFav.SetImageResource(PlayerService.isFavChecked ? Resource.Drawable.heart_fill : Resource.Drawable.heart);
        }

        

        private bool initedWindowFocus = false;
        public override void OnWindowFocusChanged(bool hasFocus)
        {
            base.OnWindowFocusChanged(hasFocus);
            if (hasFocus)
            {
                if (isSmallScreen)
                {
                    Window.DecorView.SystemUiVisibility = (StatusBarVisibility)5894;
                }
            }
            if(hasFocus && !initedWindowFocus)
            {
                initedWindowFocus = true;
                PostProcessUI();
            }
        }


        public void PostProcessUI()
        {
            if (isSmallScreen || imgBg==null) {
                return;
            }
            FrameLayout.LayoutParams flp = imgBg.LayoutParameters as FrameLayout.LayoutParams;
            if(flp != null)
            {
                flp.Width = bgContainer.Height;
                flp.Height = bgContainer.Height;
                flp.Gravity = GravityFlags.Center;
                imgBg.LayoutParameters = flp;
            }
        }


        private void BtnFav_Click(object sender, EventArgs e)
        {
            SendBroadcast(new Intent(PlayerService.NOTI_FAVO));
        }

        private void BtnVolume_Click(object sender, EventArgs e)
        {
            if(tblVolume.Visibility == ViewStates.Visible)
            {
                tblVolume.Visibility = ViewStates.Gone;
            }
            else
            {
                tblVolume.Visibility = ViewStates.Visible;
            }
        }






        #region UI Events


        private void NumProgress_StopTrackingTouch(object sender, SeekBar.StopTrackingTouchEventArgs e)
        {
            seekbarTracking = false;
            if (e.SeekBar.Progress - e.SeekBar.Max > -400)
            {
                BtnNext_Click(sender, e);
            }
        }

        private void NumDynamicRangeCompressing_StopTrackingTouch(object? sender, SeekBar.StopTrackingTouchEventArgs e)
        {
            BassPlayerImpl player = PlayerService.player;
            if (player == null)
            {
                Finish();
                return;
            }
            PrefDRC = e.SeekBar.Progress;
            player.DynamicRangeCompressed = PrefDRC;
        }

        private void NumBbtVol_StopTrackingTouch(object sender, SeekBar.StopTrackingTouchEventArgs e)
        {
            BassPlayerImpl player = PlayerService.player;
            if (player == null) {
                Finish();
                return;
            }
            PrefVolume = player.Volume;// PrefVolume;
            PrefBbtVolume = player.VolumeChannelBbt;// PrefBbtVolume;
            PrefNoiseVolume = player.VolumeChannelNoise;// PrefNoiseVolume;
        }


        int[] dspImages = {Resource.Drawable.sr_off,Resource.Drawable.sr_on,Resource.Drawable.rs_on };
        string[] dsptext = {"关","环绕","立体声音响\r\n(Crossfeed#)" };
        private void BtnSrsWow_Click(object sender, EventArgs e)
        {
            PrefSrsWow++;
            if(PrefSrsWow > 2)
            {
                PrefSrsWow = 0;
            }
            btnSrsWow.SetImageResource(dspImages[PrefSrsWow]);
            toast("立体声增强 " + dsptext[PrefSrsWow]);
            BassPlayerImpl player = PlayerService.player;
            if (player != null)
            {
                int dsptype = PrefSrsWow;
                if (dsptype == 0)
                {
                    ((DspSwitcher)player.SurroundSound).WrappedDSP = null;
                }
                if (dsptype == 1)
                {
                    ((DspSwitcher)player.SurroundSound).WrappedDSP = new SurroundDSP();
                }
                if (dsptype == 2)
                {
                    ((DspSwitcher)player.SurroundSound).WrappedDSP = new SpeakerInRoomDSP();
                }
                if(PrefMusicFx != null)
                {
                    if (PrefMusicFx.ToLower().EndsWith(".wav"))
                    {

                        PrefMusicFx = null;
                        Toast.MakeText(this, "Crossfeed# 和 脉冲响应EQ 不兼容，已停用脉冲响应EQ", ToastLength.Long).Show();
                    }
                }
                
            }
        }

        float PrefVolume
        {
            get => SharedPreferences.GetFloat("vol", 0.8f);
            set => SharedPreferences.Edit().PutFloat("vol", value).Apply();
        }

        int PrefDRC
        {
            get => SharedPreferences.GetInt("drc2", 0);
            set => SharedPreferences.Edit().PutInt("drc2", value).Apply();
        }

        float PrefBbtVolume
        {
            get => SharedPreferences.GetFloat("volbbt", 0.3f);
            set => SharedPreferences.Edit().PutFloat("volbbt", value).Apply();
        }


        float PrefNoiseVolume
        {
            get => SharedPreferences.GetFloat("volnoise", 0.3f);
            set => SharedPreferences.Edit().PutFloat("volnoise", value).Apply();
        }

        int PrefNightTimer
        {
            get => SharedPreferences.GetInt("nighttimer", 90);
            set => SharedPreferences.Edit().PutInt("nighttimer", value).Apply();
        }
        int PrefSrsWow
        {
            get => SharedPreferences.GetInt("dsp", 0);
            set => SharedPreferences.Edit().PutInt("dsp", value).Apply();
        }

        string PrefMusicFx
        {
            get => SharedPreferences.GetString("musicfx", "");
            set => SharedPreferences.Edit().PutString("musicfx", value).Apply();
        }
        int PrefSpectrumMode
        {
            get => SharedPreferences.GetInt("specmode", 1);
            set => SharedPreferences.Edit().PutInt("specmode", value).Apply();
        }
        ISharedPreferences SharedPreferences => GetSharedPreferences(PlayerService.prefslot, FileCreationMode.Private);

        string PrefLastNoise
        {
            get => SharedPreferences.GetString("lastnoise", "");
            set => SharedPreferences.Edit().PutString("lastnoise", value).Apply();
        }
        int PrefLastBbt
        {
            get => SharedPreferences.GetInt("lastbbt", -1);
            set => SharedPreferences.Edit().PutInt("lastbbt", value).Apply();
        }


        private void BtnBbtMode_Click(object sender, EventArgs e)
        {
            BBTAdapter bbtAdapter = null;
            Android.App.AlertDialog dialog = null;
            OnItemClick callback = (sender, e) =>
            {

                setBbtByIndexAndPath(e.Position, bbtAdapter);
               
                dialog?.Dismiss();
            };

            

            bbtAdapter = new BBTAdapter(this, callback);

            EventHandler<DialogClickEventArgs> handler = (sender, e) =>
            {

            };

            
            dialog = new Android.App.AlertDialog.Builder(this).SetTitle("助眠音频").SetAdapter(bbtAdapter,handler).SetPositiveButton("关闭",(IDialogInterfaceOnClickListener)null).Show();

        }

        private void setBbtByIndexAndPath(int index,BBTAdapter bbtAdapter = null)
        {
            if(bbtAdapter == null)
            {
                bbtAdapter = new BBTAdapter(this, (sender, e) => { });
            }
            if(index < 0 || index >= bbtAdapter.Count)
            {
                return;
            }
            BassPlayerImpl player = PlayerService.player;
            if (player == null) { Finish(); return; }
            player.ChannelBbtType = index; 
            if (index != 0)
            {
                PrefLastBbt = index;
            }
            try
            {
                String realPath = AndroidIO.Path.Combine(FilesDir.AbsolutePath, LauncherActivity.AUDIODIR, bbtAdapter.paths[index]);
                player.SetBbtChannelNoise(realPath);
                
            }
            catch (Exception ex)
            {
                toast("无法加载音频" + NewLine + ex.Message);
            }
            btnBbtMode.SetImageResource(bbtAdapter.icons[index]);
            toast("助眠音频" + NewLine + bbtAdapter.bbtnames[player.ChannelBbtType]);

        }
        private void BtnBbtMode_LongClick(object? sender, View.LongClickEventArgs e)
        {
            setBbtByIndexAndPath(PrefLastBbt);
            
        }

        private void BtnNoiseMode_LongClick(object? sender, View.LongClickEventArgs e)
        {
            if (!string.IsNullOrWhiteSpace(PrefLastNoise))
            {
                BassPlayerImpl player = PlayerService.player;
                if (player == null) { Finish(); return; }
                player.ChannelNoiseType = PrefLastNoise.Length;
                PlayerService.player.SetNoiseChannelNoise(PrefLastNoise); 
                toast("开启背景噪音");
            }
        }

       
        private void BtnNoiseMode_Click(object sender, EventArgs e)
        {

            Android.App.AlertDialog dialog = null;
            BassPlayerImpl player = PlayerService.player;
            if (player == null) { Finish(); return; }

            NoiseAdapter noiseAdapter = null;

            OnItemClick callback = (sender, e) =>
            {

                string path = noiseAdapter[e.Position];
                try
                {
                    PrefLastNoise = path;
                    PlayerService.player.SetNoiseChannelNoise(path);

                }
                catch (Exception ex)
                {
                    toast("无法加载声音" + NewLine + ex.Message);
                }


                PlayerService.player.ChannelNoiseType = path?.Length ?? 0;
                btnNoiseMode.SetImageResource(PlayerService.player.ChannelNoiseType > 0 ? Resource.Drawable.noiseon : Resource.Drawable.noiseoff);

                dialog?.Dismiss();
            };

            noiseAdapter = new NoiseAdapter(this, callback);


            EventHandler<DialogClickEventArgs> handler = (sender, e) =>
            {

            };
            dialog = new Android.App.AlertDialog.Builder(this).SetTitle("白噪音").SetAdapter(noiseAdapter, handler).SetPositiveButton("关闭", (IDialogInterfaceOnClickListener)null).Show();

        }



        private void BtnBassBoost_Click(object sender, EventArgs e)
        {
            Android.App.AlertDialog dialog = null;
            BassPlayerImpl player = PlayerService.player;
            if (player == null) { Finish(); return; }

            FxAdapter fxAdapter = null;
            OnItemClick callback = (sender, e) =>
            {

                string path = fxAdapter[e.Position];
                try
                {
                    PlayerService.player.LoadFx(path);
                    PrefMusicFx = path;
                    if (PrefSrsWow != 0)
                    {
                        if (path.ToLower().EndsWith(".wav"))
                        {
                            toast("脉冲响应和环绕声不兼容，已关闭环绕声");
                            this.PrefSrsWow = 0;
                            btnSrsWow.SetImageResource(Resource.Drawable.sr_off);
                        }
                    }
                }
                catch (Exception ex)
                {
                    toast("无法加载音效" + NewLine + ex.Message);
                }
                dialog?.Dismiss();
            };

            EventHandler<DialogClickEventArgs> handler = (sender, e) => { };

            fxAdapter = new FxAdapter(this, callback);

            dialog = new Android.App.AlertDialog.Builder(this)
                .SetTitle("音效")
                .SetAdapter(fxAdapter, handler)
                .SetPositiveButton("关闭", (IDialogInterfaceOnClickListener)null)
                .SetNeutralButton("如何制作音效", (sender, e) =>
                {
                    Android.Net.Uri uri = Android.Net.Uri.Parse("https://gitee.com/ZYFDroid/NightPlayer/blob/master/README.md");
                    StartActivity(new Intent(Intent.ActionView, uri));
                })
                .Show();

        }


        string NewLine => Java.Lang.JavaSystem.LineSeparator();




        int[] availableTime = { 15, 30, 45, 60,75, 90, 120, 180, 240 };
        private void BtnSleepTimer_Click(object sender, EventArgs e)
        {
            BassPlayerImpl player = PlayerService.player;
            if (player == null) { Finish(); return; }
            if (player.ScheduledStop)
            {
                for (int i = 0; i < availableTime.Length; i++)
                {
                    if (player.RemainMinute < availableTime[i])
                    {
                        player.RemainMinute = availableTime[i];
                        lblSleepTimer.Text = player.ScheduledStop ? "" + player.RemainMinute : "OFF";
                        rememberNightTimer(player);
                        return;
                    }
                }
                player.ScheduledStop = false;
                toast("关闭定时器");
                PrefNightTimer = 90;
            }
            else
            {
                player.RemainMinute = availableTime[0];
                player.ScheduledStop = true; 
                rememberNightTimer(player);
                toast(player.RemainMinute + "分钟后停止播放");
            }
            lblSleepTimer.Text = player.ScheduledStop ? "" + player.RemainMinute : "OFF";
        }
        private void BtnSleepTimer_LongClick(object? sender, View.LongClickEventArgs e)
        {
            BassPlayerImpl player = PlayerService.player;
            if (player == null) { Finish(); return; }
            player.RemainMinute = PrefNightTimer;
            player.ScheduledStop = true;

            toast(player.RemainMinute + "分钟后停止播放");
        }
        private void rememberNightTimer(BassPlayerImpl player) {
            if (DateTime.Now.Hour >= 22 || DateTime.Now.Hour <= 5)
            {
                PrefNightTimer = (int)player.RemainMinute;
            }
        }

        private void BtnShuffeMode_Click(object sender, EventArgs e)
        {
            BassPlayerImpl player = PlayerService.player;
            if (player == null) { Finish(); return; }
            PlayerController controller = PlayerService.playerController;
            controller.Shuffe = !controller.Shuffe;
            btnShuffeMode.SetImageResource(controller.Shuffe ? Resource.Drawable.shuffe_on : Resource.Drawable.shuffe_off);
            lblShuffeMode.Text = (controller.Shuffe ? "随机播放" : "顺序播放");
        }

        private void BtnLoopMode_Click(object sender, EventArgs e)
        {
            BassPlayerImpl player = PlayerService.player;
            if (player == null) { Finish(); return; }
            PlayerController controller = PlayerService.playerController;
            int mode = controller.LoopMode + 1;
            if (mode > 2) { mode = 0; }
            controller.LoopMode = mode;
            int[] arr = new int[] { Resource.Drawable.loopall, Resource.Drawable.loopone, Resource.Drawable.looplist };
            string[] msgs = {"全部循环","单曲循环","列表循环" };
            lblLoopMode.Text = msgs[mode];
            btnLoopMode.SetImageResource(arr[mode]);
            player.Looping = controller.LoopMode == 1;
        }


        private void NumVol_ProgressChanged(object sender, SeekBar.ProgressChangedEventArgs e)
        {
            BassPlayerImpl player = PlayerService.player;
            if (player == null) { Finish(); return; }
            if (e.FromUser && e.SeekBar.Id == Resource.Id.numBbtVol)
            {
                player.VolumeChannelBbt = (float)e.Progress / 100f;
            }
            if (e.FromUser && e.SeekBar.Id == Resource.Id.numNoiseVol)
            {
                player.VolumeChannelNoise = (float)e.Progress / 100f;
            }
            if (e.FromUser && e.SeekBar.Id == Resource.Id.numMainVol)
            {
                player.Volume = (float)e.Progress / 100f;
            }
        }


        void UpdateVolumePanelState()
        {
            BassPlayerImpl player = PlayerService.player;
            if (player == null) { Finish(); return; }
            numMainVol.Progress = (int)(player.Volume * 100f);
            numNoiseVol.Progress = (int)(player.VolumeChannelNoise * 100f);
            numBbtVol.Progress = (int)(player.VolumeChannelBbt * 100f);
            numDynamicRangeCompressing.Progress = player.DynamicRangeCompressed;
        }

        private void BtnExit_Click(object sender, EventArgs e)
        {

            BassPlayerImpl player = PlayerService.player;
            if (player == null) { Finish(); return; }
            player.AquireRaiseStop();
        }


        private void NumProgress_ProgressChanged(object sender, SeekBar.ProgressChangedEventArgs e)
        {
            if (seekbarTracking)
            {
                BassPlayerImpl player = PlayerService.player;
                if (player == null) { Finish(); return; }
                player.CurrentPosition = e.Progress;
            }
        }

        private void BtnPlay_Click(object sender, EventArgs e)
        {

            BassPlayerImpl player = PlayerService.player;
            if (player == null) { Finish(); return; }
            player.PlayOrPause();
            btnPlay.SetImageResource(player.IsPlaying ? Resource.Drawable.pause : Resource.Drawable.play);

            PlayerService.onUserAction(this);
        }
        
        private void BtnNext_Click(object sender, EventArgs e)
        {
            BassPlayerImpl player = PlayerService.player;
            if (player == null) { Finish(); return; }
            PlayerService.playerController.onNextButtonClick();
            PlayerService.onUserAction(this);
        }

        private void BtnPrev_Click(object sender, EventArgs e)
        {
            BassPlayerImpl player = PlayerService.player;
            if (player == null) { Finish(); return; }
            PlayerService.playerController.onPrevButtonClick();
            PlayerService.onUserAction(this);
        }

        #endregion
        #region Animation Ticking
        bool seekbarTracking = false;
        Handler hWnd = new Handler();
        Action ticking = null;

        private Toast PrevToast = null;
        public void toast(String str)
        {
            try { PrevToast?.Cancel(); } catch { }
            PrevToast = Toast.MakeText(this, str, ToastLength.Short);
            PrevToast.Show();
        }

        public void OnTick()
        {
            if (timerrunning)
            {
                BassPlayerImpl player = PlayerService.player;
                if (player == null) { Finish(); return; }

                #region Scheduled UI Task
                long currentpos = player.CurrentPosition;
                if (!seekbarTracking)
                {
                    numProgress.Max = (int)player.TotalPosition;
                    numProgress.Progress = (int)currentpos;
                }

                lblCurrentTime.Text = timeToString(currentpos);
                lblTotalTime.Text = timeToString(player.TotalPosition);

                lblSleepTimer.Text = player.ScheduledStop ? "" + player.RemainMinute : "OFF";

                lblSleepTimer2.Text = player.ScheduledStop ? timeToString(player.RemainSecond * 1000) : "定时停止";

                #endregion
            }
            if (activityExited) { timerrunning = false; return; }
            hWnd.PostDelayed(ticking, isEink ? 1000 : 100);
        }

        String timeToString(long ms)
        {
            long minutes = ms / 60000;
            long second = (ms % 60000) / 1000;
            return String.Format("{0:D2}:{1:D2}", minutes, second);
        }

        #endregion
        #region X-Context Event Handler
        BroadcastReceiver eventReceiver = null;

        class EventListener : BroadcastReceiver
        {
            MainActivity accessor;
            public EventListener(MainActivity accessor)
            {
                this.accessor = accessor;
            }
            public override void OnReceive(Context context, Intent intent)
            {
                Log.Debug("NightPlayer", intent.Action);
                Console.WriteLine(intent.Action);
                switch (intent.Action) {
                    case PlayerService.BROADCAST_COVERCHANGED:
                        accessor.loadCover();
                        break;
                    case PlayerService.BROADCAST_SONGCHANGED:
                        accessor.loadInfo();
                        break;
                    case PlayerService.BROADCAST_EXIT:
                        accessor.Finish();
                        break;
                    case PlayerService.BROADCAST_PLAYCHANGE:
                        accessor.btnPlay.SetImageResource(PlayerService.player.IsPlaying ? Resource.Drawable.pause : Resource.Drawable.play);
                        break;
                    case PlayerService.BROADCAST_FAV_ON:
                        accessor.btnFav.SetImageResource(Resource.Drawable.heart_fill);
                        break;
                    case PlayerService.BROADCAST_FAV_OFF:
                        accessor.btnFav.SetImageResource(Resource.Drawable.heart);
                        break;
                }
            }
        }

        #endregion
        #region Info Loader

        #region cover

        void loadCover()
        {
            BassPlayerImpl player = PlayerService.player;
            if (player == null) { Finish(); return; }

            if (player.cover == null)
            {
                (imgCover).SetImageResource(Resource.Drawable.default_cover);
                if(imgBg != null)
                {

                    imgBg.Visibility = ViewStates.Gone;
                }
            }
            else
            {
                Bitmap circleCover = (player.cover);
                if (imgBg != null)
                {
                    imgBg.Visibility = ViewStates.Visible;
                    Bitmap bg = Bitmap.CreateScaledBitmap(player.cover, 64, 64, true);
                    Bitmap blurdbg = Blur(this, bg);
                    bg.Dispose();
                    imgBg?.SetImageBitmap(blurdbg);
                }
                
                imgCover.SetImageBitmap(circleCover);
                GC.Collect();
                Java.Lang.JavaSystem.Gc();
            }
        }
        float dip2px(float dip)
        {
            return dip * ((float)Resources.Configuration.DensityDpi / 160f);
        }
        private static float BLUR_RADIUS = 24.0f;

        public static Bitmap Blur(Context ctx, Bitmap image)
        {
            int width = (image.Width) + 24;
            int height = (image.Height) + 24;

            Bitmap inputBitmap = Bitmap.CreateBitmap(width, height,
                                Bitmap.Config.Argb8888);
            int brightness = -172;
            ColorMatrix cMatrix = new ColorMatrix();
            cMatrix.Set(new float[] { 1, 0, 0, 0, brightness, 0, 1,
                                0, 0, brightness,
                                0, 0, 1, 0, brightness, 0, 0, 0, 1, 0 });

            Paint paint = new Paint();
            paint.SetColorFilter(new ColorMatrixColorFilter(cMatrix));

            Canvas canvas = new Canvas(inputBitmap);
            canvas.DrawBitmap(image, 12, 12, paint);
            Bitmap outputBitmap = Bitmap.CreateBitmap(inputBitmap);

            RenderScript rs = RenderScript.Create(ctx);
            ScriptIntrinsicBlur theIntrinsic = ScriptIntrinsicBlur.Create(rs, Element.U8_4(rs));
            Allocation tmpIn = Allocation.CreateFromBitmap(rs, inputBitmap);
            Allocation tmpOut = Allocation.CreateFromBitmap(rs, outputBitmap);
            theIntrinsic.SetRadius(BLUR_RADIUS);
            theIntrinsic.SetInput(tmpIn);
            theIntrinsic.ForEach(tmpOut);
            tmpOut.CopyTo(outputBitmap);
            inputBitmap.Dispose();
            return outputBitmap;
        }

        #endregion

        void loadInfo() {
            BassPlayerImpl player = PlayerService.player;
            if (player == null) { Finish(); return; }

            btnPlay.SetImageResource(player.IsPlaying ? Resource.Drawable.pause : Resource.Drawable.play);
            lblTitle.Text = player.title;
            lblSubtitle.Text = player.artist + " - " + player.album;
            numProgress.Max = (int)player.TotalPosition;

            if (null != listMain.Adapter) {
                if (listMain.Adapter is SongAdapter) {
                    (listMain.Adapter as SongAdapter)!.NotifyDataSetChanged();
                }
                
            }
            if (null != listFolder.Adapter)
            {
                if (listFolder.Adapter is FolderAdapter)
                {
                    (listFolder.Adapter as FolderAdapter)!.NotifyDataSetChanged();
                }

            }
            UpdateUIState();
        }


        void UpdateUIState()
        {
            BassPlayerImpl player = PlayerService.player;
            if (player == null) { Finish(); return; }
            PlayerController controller = PlayerService.playerController;
            int[] arr = new int[] { Resource.Drawable.loopall, Resource.Drawable.loopone, Resource.Drawable.looplist };
            btnLoopMode.SetImageResource(arr[controller.LoopMode]);
            btnShuffeMode.SetImageResource(controller.Shuffe ? Resource.Drawable.shuffe_on : Resource.Drawable.shuffe_off);
            lblSleepTimer.Text = player.ScheduledStop ? "" + player.RemainMinute : "OFF";
            btnNoiseMode.SetImageResource(player.ChannelNoiseType > 0 ? Resource.Drawable.noiseon : Resource.Drawable.noiseoff);
            arr = new int[] { Resource.Drawable.bbtoff, Resource.Drawable.bbt2hz, Resource.Drawable.bbt5hz, Resource.Drawable.bbt5hz, Resource.Drawable.bbt8hz, Resource.Drawable.bbt8hz, Resource.Drawable.bbt20hz };
            btnBbtMode.SetImageResource(arr[player.ChannelBbtType]);
            UpdateVolumePanelState();
            lblShuffeMode.Text = (controller.Shuffe ? "随机播放" : "顺序播放");
            string[] msgs = { "全部循环", "单曲循环", "列表循环" };
            lblLoopMode.Text = msgs[controller.LoopMode];
        }
        #endregion
        #region Activity Lifecycle

        bool activityExited = false;
        bool timerrunning = false;
        protected override void OnResume()
        {
            base.OnResume();
            loadInfo();
            loadCover();
            timerrunning = true;
        }
        protected override void OnPause()
        {
            timerrunning = false;
            base.OnPause();
        }

        public override void OnBackPressed()
        {
            activityExited = true;
            base.OnBackPressed();
        }

        protected override void OnDestroy()
        {
            base.OnDestroy();
            UnregisterReceiver(eventReceiver);
        }

        #endregion
        #region List


        private void BtnPlaylist_Click(object sender, EventArgs e)
        {


            listMain.Adapter = (new SongAdapter(PlayerService.playerController.CurrentList, this,ListMain_ItemClick));
            hWnd.PostDelayed(delegate
            {
                int position = PlayerService.playerController.CurrentList.Songs.IndexOf(PlayerService.playerController.CurrentPlaying);
                
                listMain.SetSelection(position);
            }, 30);
            pager.SetCurrentItem(1,true);
        }

        private void ListMain_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
        {
            if (null != listMain.Adapter)
            {
                if (listMain.Adapter is SongAdapter)
                {
                    SongAdapter songAdapter = (listMain.Adapter as SongAdapter);
                    SongEntry se = songAdapter[e.Position];
                    PlayList pl = songAdapter.list;
                    PlayerService.playerController.CurrentList = pl;
                    PlayerService.playerController.CurrentPlaying = se;
                    PlayerService.playerController.ImReady();
                    PlayerService.player.Play();

                }
               
            }
        }

        private void ListFolder_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
        {
            if (null != listFolder.Adapter)
            {
                if (listFolder.Adapter is FolderAdapter)
                {
                    FolderAdapter folderAdapter = (listFolder.Adapter as FolderAdapter);
                    PlayList pl = folderAdapter[e.Position];
                    listMain.Adapter = (new SongAdapter(pl, this, ListMain_ItemClick));
                    if (PlayerService.playerController.CurrentList == pl)
                    {
                        hWnd.PostDelayed(delegate
                        {
                            int position = PlayerService.playerController.CurrentList.Songs.IndexOf(PlayerService.playerController.CurrentPlaying);
                            listMain.SetSelection(position);
                        }, 30);
                    }
                    pager.SetCurrentItem(1, true);
                }

            }
        }


        public delegate void OnItemClick(object sender, AdapterView.ItemClickEventArgs e);

        class FolderAdapter : BaseAdapter<PlayList>
        {
            private List<PlayList> list;
            private MainActivity accessor;
            private OnItemClick click;
            public FolderAdapter(List<PlayList> list, MainActivity accessor,OnItemClick click)
            {
                this.list = list;
                this.accessor = accessor;
                this.click = click;
            }

            public void onDataSetChanged() {
                NotifyDataSetChanged();
            }

            public override PlayList this[int position] => list[position];

            public override int Count => list.Count;

            public override long GetItemId(int position)
            {
                return position;
            }

            public override View GetView(int position, View convertView, ViewGroup parent)
            {
                View v = null;
                if (convertView != null)
                {
                    v = convertView;
                    v.FindViewById<TextView>(Resource.Id.txtName).SetTextColor(new Color(accessor.GetColor(Resource.Color.default_item)));
                    v.FindViewById<TextView>(Resource.Id.txtName).Typeface = Typeface.Default;

                }
                else {
                    v = accessor.LayoutInflater.Inflate(Resource.Layout.adapter_play, null, false);
                    v.FindViewById<TextView>(Resource.Id.txtName).SetTextColor(new Color(accessor.GetColor(Resource.Color.default_item)));

                    v.FindViewById<TextView>(Resource.Id.txtName).Typeface = Typeface.Default;
                    v.Click += delegate
                    {
                        click.Invoke(this, new AdapterView.ItemClickEventArgs(null, null, (int)v.Tag, 0));
                    };
                }
                PlayerController pc = PlayerService.playerController;
                if (pc != null) {
                    if (this[position].Equals(pc.CurrentList)) {
                        v.FindViewById<TextView>(Resource.Id.txtName).SetTextColor(new Color(accessor.GetColor(Resource.Color.selected_item)));

                        v.FindViewById<TextView>(Resource.Id.txtName).Typeface = Typeface.DefaultBold;
                    }
                }
                v.Tag = position;
                v.FindViewById<ImageView>(Resource.Id.imgIcon).SetImageResource(this[position] is VirtualDir ? Resource.Drawable.ic_folder_next : Resource.Drawable.folder);
                v.FindViewById<TextView>(Resource.Id.txtName).Text = this[position].Name;
                return v;
            }
        }


        class SongAdapter : BaseAdapter<SongEntry>
        {
            public PlayList list;
            public List<SongEntry> cachedEntries;
            private MainActivity accessor;

            private OnItemClick click;
            public SongAdapter(PlayList list, MainActivity accessor,OnItemClick click)
            {
                this.list = list;
                this.accessor = accessor;
                this.click = click;
                this.cachedEntries = list.Songs;
            }
            public override void NotifyDataSetChanged()
            {
                this.cachedEntries = list.Songs;
                base.NotifyDataSetChanged();
            }
            public override SongEntry this[int position] => cachedEntries[position];

            public override int Count => cachedEntries.Count;

            public override long GetItemId(int position)
            {
                return position;
            }

            public override View GetView(int position, View convertView, ViewGroup parent)
            {
                View v = null;
                if (convertView != null)
                {
                    v = convertView;
                    v.FindViewById<TextView>(Resource.Id.txtName).SetTextColor(new Color(accessor.GetColor(Resource.Color.default_item)));

                    v.FindViewById<TextView>(Resource.Id.txtName).Typeface = Typeface.Default;
                }
                else
                {
                    v = accessor.LayoutInflater.Inflate(Resource.Layout.adapter_play, null, false);
                    v.FindViewById<ImageView>(Resource.Id.imgIcon).SetImageResource(Resource.Drawable.playlist);
                    v.FindViewById<TextView>(Resource.Id.txtName).SetTextColor(new Color(accessor.GetColor(Resource.Color.default_item)));

                    v.FindViewById<TextView>(Resource.Id.txtName).Typeface = Typeface.Default;
                    v.Click += delegate
                    {
                        click.Invoke(this, new AdapterView.ItemClickEventArgs(null, null, (int)v.Tag, 0));
                    };
                }
                PlayerController pc = PlayerService.playerController;
                if (pc != null)
                {
                    if (this[position] == pc.CurrentPlaying)
                    {
                        v.FindViewById<TextView>(Resource.Id.txtName).SetTextColor(new Color(accessor.GetColor(Resource.Color.selected_item)));

                        v.FindViewById<TextView>(Resource.Id.txtName).Typeface = Typeface.DefaultBold;
                    }
                }
                v.FindViewById<TextView>(Resource.Id.txtName).Text = this[position].Name;
                v.Tag = position;
                return v;
            }
        }

        public class BBTAdapter : BaseAdapter<String>
        {
            public List<string> bbtnames = new List<string>();
            public List<int> icons = new List<int>();
            public List<string> paths = new List<string>();
            private MainActivity accessor;

            public static string[] bbtPath = { "",
                    "bbt_2.ogg",
                    "bbt_4.ogg",
                    "bbt_5.ogg",
                    "bbt_78.ogg" ,
                    "bbt_8.ogg",
                    "bbt_20.ogg"
                };

            private OnItemClick click;
            public BBTAdapter(MainActivity accessor, OnItemClick click)
            {
                string[] msgs = {"关闭助眠音频", "2Hz (深睡眠)", "4Hz (冥想)", "5Hz (梦)","7.83Hz （舒曼波）", "8Hz (放松)","20Hz (超频模式开启！)"};
                int[] arr = new int[] { Resource.Drawable.bbtoff, Resource.Drawable.bbt2hz, Resource.Drawable.bbt5hz, Resource.Drawable.bbt5hz, Resource.Drawable.bbt8hz, Resource.Drawable.bbt8hz, Resource.Drawable.bbt20hz };
                
                this.bbtnames.AddRange(msgs);
                this.icons.AddRange(arr);
                this.paths.AddRange(bbtPath);
                this.accessor = accessor;
                this.click = click;
            }

            public void onDataSetChanged()
            {
                NotifyDataSetChanged();
            }
            public override string this[int position] => bbtnames[position];

            public override int Count => bbtnames.Count;

            public override long GetItemId(int position)
            {
                return position;
            }

            public override View GetView(int position, View convertView, ViewGroup parent)
            {
                View v = null;
                if (convertView != null)
                {
                    v = convertView;
                    v.FindViewById<TextView>(Resource.Id.txtName).SetTextColor(new Color(accessor.GetColor(Resource.Color.normal_item)));
                }
                else
                {
                    v = accessor.LayoutInflater.Inflate(Resource.Layout.adapter_list, null, false);
                    
                    v.FindViewById<TextView>(Resource.Id.txtName).SetTextColor(new Color(accessor.GetColor(Resource.Color.normal_item)));
                    v.Click += delegate
                    {
                        click.Invoke(this, new AdapterView.ItemClickEventArgs(null, null, (int)v.Tag, 0));
                    };
                }
                v.FindViewById<ImageView>(Resource.Id.imgIcon).SetImageResource(icons[position]);
                v.FindViewById<TextView>(Resource.Id.txtName).Text = this[position];
                v.Tag = position;
                return v;
            }
        }
        
        
        class FxAdapter : BaseAdapter<String>
        {
            public List<string> fxpaths;
            private MainActivity accessor;

            private OnItemClick click;
            public FxAdapter(MainActivity accessor, OnItemClick click)
            {
                fxpaths = new List<string>();
                fxpaths.Add("");
                String fileroot = AndroidIO.Path.Combine(CurrentDirectorySongProvider.MusicRoot, ".musicfx");
                if (AndroidIO.Directory.Exists(fileroot)) {
                    AndroidIO.Directory.EnumerateFiles(fileroot, "*.wav").ToList().ForEach(f => fxpaths.Add(f));
                    AndroidIO.Directory.EnumerateFiles(fileroot, "*.eq").ToList().ForEach(f => fxpaths.Add(f)) ;
                }
                this.accessor = accessor;
                this.click = click;
            }

            public void onDataSetChanged()
            {
                NotifyDataSetChanged();
            }
            public override string this[int position] => fxpaths[position];

            public override int Count => fxpaths.Count;

            public override long GetItemId(int position)
            {
                return position;
            }

            public override View GetView(int position, View convertView, ViewGroup parent)
            {
                View v = null;
                if (convertView != null)
                {
                    v = convertView;
                    v.FindViewById<TextView>(Resource.Id.txtName).SetTextColor(new Color(accessor.GetColor(Resource.Color.normal_item)));
                }
                else
                {
                    v = accessor.LayoutInflater.Inflate(Resource.Layout.adapter_list, null, false);
                    v.FindViewById<ImageView>(Resource.Id.imgIcon).SetImageResource(Resource.Drawable.ic_spectrum_center);
                    v.FindViewById<TextView>(Resource.Id.txtName).SetTextColor(new Color(accessor.GetColor(Resource.Color.normal_item)));
                    v.Click += delegate
                    {
                        click.Invoke(this, new AdapterView.ItemClickEventArgs(null, null, (int)v.Tag, 0));
                    };
                }
               
                v.FindViewById<TextView>(Resource.Id.txtName).Text = String.IsNullOrEmpty(this[position]) ? "<无音效>" : AndroidIO.Path.GetFileName(this[position]);
                v.Tag = position;
                return v;
            }
        }
        
        class NoiseAdapter : BaseAdapter<String>
        {
            public List<string> fxpaths;
            private MainActivity accessor;

            private OnItemClick click;
            public NoiseAdapter(MainActivity accessor, OnItemClick click)
            {
                fxpaths = new List<string>();
                fxpaths.Add("");
                String fileroot = AndroidIO.Path.Combine(CurrentDirectorySongProvider.MusicRoot, ".noise");
                if (AndroidIO.Directory.Exists(accessor.FilesDir.AbsolutePath)) {
                    AndroidIO.Directory.EnumerateFiles(AndroidIO.Path.Combine(accessor.FilesDir.AbsolutePath,LauncherActivity.AUDIODIR), "*.nof").OrderBy(f=>f).ToList().ForEach(f => fxpaths.Add(f)) ;
                }
                if (AndroidIO.Directory.Exists(fileroot)) {
                    AndroidIO.Directory.EnumerateFiles(fileroot, "*.nof").OrderBy(f => f,StringComparer.CurrentCultureIgnoreCase).ToList().ForEach(f => fxpaths.Add(f)) ;
                }
                this.accessor = accessor;
                this.click = click;
            }

            public void onDataSetChanged()
            {
                NotifyDataSetChanged();
            }
            public override string this[int position] => fxpaths[position];

            public override int Count => fxpaths.Count;

            public override long GetItemId(int position)
            {
                return position;
            }

            public override View GetView(int position, View convertView, ViewGroup parent)
            {
                View v = null;
                if (convertView != null)
                {
                    v = convertView;
                    v.FindViewById<TextView>(Resource.Id.txtName).SetTextColor(new Color(accessor.GetColor(Resource.Color.normal_item)));
                }
                else
                {
                    v = accessor.LayoutInflater.Inflate(Resource.Layout.adapter_list, null, false);
                    v.FindViewById<ImageView>(Resource.Id.imgIcon).SetImageResource(Resource.Drawable.ic_spectrum_center);
                    v.FindViewById<TextView>(Resource.Id.txtName).SetTextColor(new Color(accessor.GetColor(Resource.Color.normal_item)));
                    v.Click += delegate
                    {
                        click.Invoke(this, new AdapterView.ItemClickEventArgs(null, null, (int)v.Tag, 0));
                    };
                }
               
                v.FindViewById<TextView>(Resource.Id.txtName).Text = String.IsNullOrEmpty(this[position]) ? "<关闭背景噪音>" : AndroidIO.Path.GetFileName(this[position]);
                v.Tag = position;
                return v;
            }
        }

        #endregion
    }
}

